#pragma once

#include "VisioCommon.h"
#include <algorithm>
#include <vector>
#include <opencv2\opencv.hpp>
#include "Camera.h"
#include "ImageData.h"

//forward declarations
class CImageMatch;


//typedef
typedef std::pair<CImageData*, CImageData*> ImageDataPair;
typedef std::pair<UINT, UINT> KeyPointIndexMatch;
typedef std::pair<cv::Point2d, cv::Point2d> KeyPointMatch;
typedef std::vector<KeyPointIndexMatch> ImageDataIntersection;
typedef std::pair<UINT, UINT> ImagePairIndex;

#define FIRST 0 
#define SECOND 1

#define FIRST_IMAGE(pMatch) (pMatch->GetImageData(FIRST))
#define SECOND_IMAGE(pMatch) (pMatch->GetImageData(SECOND))

class CImageMatch
{
public:
	CImageMatch(CImageData* ImA, CImageData* ImB, int NumInliners, double InlinersRatio);
	~CImageMatch();
	std::pair<cv::Mat*, cv::Mat*> GetMatchingPoints();
	cv::Mat GetEMatrix() const;
	ImageDataIntersection Intersect(CImageData* ImA, CImageData* ImB);
	UINT GetNumMatches() const;
	double GetInlinersScore() const;

	//return a pair of the indeices of the matched images
	ImagePairIndex GetImageIndices() const;

	//return the actuall data of the image e.g the texture
	cvImage GetImageForTexture(UINT index);
	
	//return the imagedata class
	CImageData* GetImageData( UINT index ) const;



	UINT GetNumInliners() const;
	KeyPointMatch GetKeyPoints(UINT index) const;
	KeyPointIndexMatch GetKeyPointsIndex(UINT index) const;
	cv::Mat CalculateEmatrixInternal(int n, double* _rPoints, double* _lPoints, double ransac_threshold, int ransac_rounds, cv::Mat K1, cv::Mat K2) const;

	void NormalizePoints(int n, double* _rPoints,double* _lPoints,double* rPointsNorm,double* lPointsNorm,cv::Mat K1,cv::Mat K2) const;
	void GetMatchedPointsAsDouble(double* lPoints, double* rPoints) const;
	cv::Mat GetIntrinMatrixForImage(UINT index) const;
private:
	ImagePairIndex m_ImageIndex;
	UINT m_NumberOfMatches;
	double m_InlinersRatio;
	ImageDataPair m_ImageData;
	ImageDataIntersection m_MatchedKeyPoints;
	int m_NumInliners;
};